#include"DirContral.h"

//创建文件夹头文件
#include<sys/stat.h>
#include<sys/types.h>
#include<locale.h>
#include<cstdlib>
#include<dirent.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fstream>
#include<sys/stat.h>
#include<algorithm>
#include"TcpConnection.h"
#include<thread>
#include<chrono>


#define BUFFERSIZE 1024*20


DirContral::DirContral(/* args */)
{
}

DirContral::~DirContral()
{
}

DirContral &DirContral::getInstance()
{
    // TODO: 在此处插入 return 语句
    static DirContral instance;
    return instance;
}

bool DirContral::directoryExists(std::string filePath)
{
    struct stat info;
    if (stat(filePath.c_str(), &info) != 0) {
        return false;
    }
    return (info.st_mode & S_IFDIR) != 0;

    return false;
}

bool DirContral::isFileExist(const std::string &path)
{
    FILE *file = fopen(path.c_str(),"r");
    if(file != nullptr){
        fclose(file);
        return true;
    }
    return false;
}

CloudDrive::MessageReturn DirContral::creatNewFolder(std::string filePath)
{
    if(directoryExists(filePath)){
        return CloudDrive::MessageReturn::NEW_DIR_EXIST;
    }

    mode_t mode = 0777;
    if(mkdir(filePath.c_str(),mode)!=0) {
        return CloudDrive::MessageReturn::NEW_DIR_NO;
    }
    return CloudDrive::MessageReturn::NEW_DIR_OK;
}

CloudDrive::MessageReturn DirContral::deleteFolder(std::string filePath)
{
    struct stat fileStat;
    if(stat(filePath.c_str(), &fileStat) != 0) {
        // 文件或目录不存在
        return CloudDrive::MessageReturn::DELETE_FILE_NOTEXIST;
    }
    
    if(S_ISREG(fileStat.st_mode)) {
        // 是文件，尝试删除
        int ret = remove(filePath.c_str());
        if(ret == 0) 
            return CloudDrive::MessageReturn::DELETE_FILE_OK;
        else
            return CloudDrive::MessageReturn::DELETE_FRIEND_NO;
    } 
    else if(S_ISDIR(fileStat.st_mode)) {
        // 是目录，递归删除
        if(removeDirectoryRecursively(filePath)) {
            return CloudDrive::MessageReturn::DELETE_FILE_OK;
        } else {
            return CloudDrive::MessageReturn::DELETE_FRIEND_NO;
        }
    }
    
    // 既不是文件也不是目录
    return CloudDrive::MessageReturn::DELETE_FRIEND_NO;
}

CloudDrive::MesBackFile DirContral::getFileList(const std::string filePath)
{
    CloudDrive::MesBackFile fileListInfo;
    fileListInfo.FileNum = 0;
    DIR *dir = opendir(filePath.c_str());
    if(dir == nullptr) std::cout<<"dasss";
    struct dirent *entry;
    struct stat fileStat;

    while ((entry = readdir(dir)) != nullptr)
    {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        std::string subFilePath = filePath + '/' + entry->d_name;
        std::memcpy(fileListInfo.fileInfo[fileListInfo.FileNum].fileName,entry->d_name,CloudDrive::MAX_FILENAME_LEN-1);
        if(stat(subFilePath.c_str(),&fileStat)==0) {
            fileListInfo.fileInfo[fileListInfo.FileNum].fileSize = fileStat.st_size;
            const char* typeStr = S_ISREG(fileStat.st_mode) ? "file" : "dir";
            snprintf(fileListInfo.fileInfo[fileListInfo.FileNum].fileType, CloudDrive::MAX_FILENAME_LEN,"%s", typeStr);
            struct tm* timeinfo = localtime(&fileStat.st_mtime);
            char buffer[80];
            strftime(buffer,sizeof(buffer),"%Y-%m-%d %H:%M:%S",timeinfo);
            std::memcpy(fileListInfo.fileInfo[fileListInfo.FileNum].fileData,buffer,CloudDrive::MAX_FILEDATA_LEN-1);
        }
        fileListInfo.FileNum++;
    }
    closedir(dir);
    return fileListInfo;
}

// 安全地递归删除目录
bool DirContral::removeDirectoryRecursively(const std::string& path)
{
    DIR *dir = opendir(path.c_str());
    if (!dir) {
        return false;
    }
    
    struct dirent *entry;
    while ((entry = readdir(dir)) != nullptr) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        
        std::string subPath = path + "/" + entry->d_name;
        struct stat subStat;
        
        if (stat(subPath.c_str(), &subStat) == 0) {
            if (S_ISDIR(subStat.st_mode)) {
                // 递归删除子目录
                if (!removeDirectoryRecursively(subPath)) {
                    closedir(dir);
                    return false;
                }
            } else {
                // 删除文件
                if (remove(subPath.c_str()) != 0) {
                    closedir(dir);
                    return false;
                }
            }
        }
    }
    
    closedir(dir);
    
    // 删除空目录
    return (rmdir(path.c_str()) == 0);
}

bool DirContral::writeDataToFile(const std::string &filePath, const std::vector<uint8_t> &data, uint64_t offset, std::mutex &fileMutex, bool createIfNotExist)
{
    std::lock_guard<std::mutex> fileGuard(fileMutex);
    
        // 用 std::fstream 支持读写
    std::fstream file(filePath,std::ios::in | std::ios::out | std::ios::binary);
    if (!file.is_open()) {
        if (!createIfNotExist) return false;
        // 文件不存在，则先创建空文件
        {
            std::ofstream tmp(filePath,std::ios::out | std::ios::binary);
        }
        // 再用读写模式打开
        file.open(filePath,std::ios::in | std::ios::out | std::ios::binary);
        if (!file.is_open()) return false;
    }
    
    // 检查文件是否成功打开
    if (!file.is_open()) {
        return false;
    }
    
    // 将文件指针移动到指定偏移位置
    file.seekp(offset, std::ios::beg);
    
    file.write(reinterpret_cast<const char*>(data.data()), data.size());
    
    // 检查写入是否成功
    if (!file.good()) {
        file.close();
        return false;
    }
    
    // 关闭文件
    file.close();
    return true;
}

void DirContral::downLoadFile(const std::string &fileName, const std::string &filePath, 
                              const std::string &fileIdenter, std::shared_ptr<TcpConnection> conn)
{
    // 生成控制信息
    std::cout<<std::this_thread::get_id()<<std::endl;
    auto contral = std::make_shared<CloudDrive::UploadControl>();
    {
        std::lock_guard<std::mutex> lk(contralMutex);
        if(downContral.find(fileIdenter) == downContral.end()){
            downContral.emplace(fileIdenter,contral);
        }
    }

    std::cout<<fileIdenter<<"\t"<<fileIdenter.size()<<std::endl;
    if(downContral.find(fileIdenter)==downContral.end()){
        std::cout<<"error"<<std::endl;
    }

    std::string fileAllPath = filePath + "/" + fileName;

    std::cout << "准备下载文件: " << fileName << " 路径: " << fileAllPath << std::endl;

    // 打开文件
    std::ifstream file(fileAllPath, std::ios::binary);
    if(!file.is_open()){
        std::cerr << "文件打开失败: " << fileAllPath << " 错误: " << std::strerror(errno) << std::endl;
        return;
    }

    // 获取文件大小
    struct stat statbuf;
    if(0 != stat(fileAllPath.c_str(), &statbuf)){
        std::cerr << "获取文件状态失败: " << filePath << " 错误: " << std::strerror(errno) << std::endl;
        file.close();
        return;
    }

    uint32_t fileSize = statbuf.st_size;
    uint32_t totalSend = 0;
    std::cout << "开始下载文件，大小: " << fileSize << " 字节" << std::endl;

    // 构建请求头
    CloudDrive::Packet pkt;
    pkt.header.type = CloudDrive::MessageType::DOWNFILE;
    pkt.header.timestamp = CloudDrive::now_millis();
    pkt.header.version = CloudDrive::PROTOCOL_VERSION;

    uint32_t id = 0;
    std::vector<char> buffer(BUFFERSIZE);

    while(totalSend < fileSize){
        // 控制锁 - 处理暂停/取消
        {
            std::unique_lock<std::mutex> lk(contral->mtx);
            contral->cv.wait(lk, [&](){
                return !contral->paused || contral->cancelled;
            });
            if(contral->cancelled){
                std::cout << "下载已取消: " << fileName << std::endl;
                break;
            }
        }

        // 计算本次读取大小
        size_t bytesToRead = std::min(static_cast<uint32_t>(BUFFERSIZE), fileSize - totalSend);
        
        // 读取文件数据
        file.read(buffer.data(), bytesToRead);
        size_t bytesRead = file.gcount();

        // 检查读取错误
        if(bytesRead == 0){
            if(file.eof()){
                std::cout << "已到达文件末尾" << std::endl;
                break;
            } else if(file.fail()){
                std::cerr << "读取文件失败: " << std::strerror(errno) << std::endl;
                break;
            }
        }

        // 准备发送数据
        std::vector<uint8_t> data(buffer.begin(), buffer.begin() + bytesRead);
        CloudDrive::FileInfoSave fileSave = CloudDrive::makeFileDataSave(
            "", "", filePath, filePath, fileSize, bytesRead, totalSend, id, fileIdenter, data);
        
        // 保存文件数据到缓冲区
        {
            std::lock_guard<std::mutex> lk(fileDataMutex);
            fileData.emplace(std::make_pair(fileIdenter, id), fileSave);
        }

        // 发送数据 (最多重试3次)
        bool sendSuccess = false;
        int retryCount = 3;
        
        while (retryCount > 0 && !sendSuccess)
        {
            try
            {
                CloudDrive::Packet pkt1 = CloudDrive::makeFilePacket(
                    pkt, "", "", fileName, filePath, fileSize, bytesRead, totalSend, id, fileIdenter, data, 4);
                conn->enqueueSend(pkt1);
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                sendSuccess = true;
                std::cout << "已发送块 " << id << ", 大小: " << bytesRead << " 字节" <<data.size()<<"  "<< pkt1.body.size()<<"\t"<<downContral.size()<< std::endl;
            }
            catch(const std::exception& e)
            {
                retryCount--;
                std::cerr << "发送失败 (重试剩余: " << retryCount 
                          << "): " << e.what() << std::endl;
                
                // 短暂延迟后重试
                if(retryCount > 0)
                    std::this_thread::sleep_for(std::chrono::milliseconds(500));
            }
        }

        // 如果所有重试都失败
        if(!sendSuccess){
            std::cerr << "文件 " << fileName << " 块 " << id 
                      << " 发送失败，终止下载" << std::endl;
            break;
        }

        totalSend += bytesRead;
        id++;
    }

    // 关闭文件
    file.close();

    // 检查是否成功完成下载
    if(totalSend >= fileSize){
        std::cout << "文件下载完成: " << fileName 
                  << " (" << totalSend << "/" << fileSize << " 字节)" << std::endl;
    } else {
        std::cout << "文件下载中断: " << fileName 
                  << " (" << totalSend << "/" << fileSize << " 字节)" << std::endl;
    }
}

void DirContral::fileDownSet(std::string fileSet,std::string fileIdenter)
{
    // std::cout<<std::this_thread::get_id()<<std::endl;
    std::lock_guard<std::mutex> lk(contralMutex);
    // std::cout<<<<std::endl;
    for(const auto& c:downContral){
        std::cout<<"key"<<c.first<<"\tcsize"<<c.first.size()<<"\t"<<fileIdenter<<"\t"<<fileIdenter.size()<<std::endl;
        if(c.first == fileIdenter){
            std::cout<<"ffjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"<<std::endl;
        }
    }
    if(downContral.find(fileIdenter)==downContral.end()){
        
        return;
    }
    if(fileSet == "Pause"){
        downContral[fileIdenter]->paused = true;
    }
    else if(fileSet == "Continue"){
        downContral[fileIdenter]->paused = false;
    }
    else{
        downContral[fileIdenter]->cancelled = true;
    }
    downContral[fileIdenter]->cv.notify_one();
}

